package pl.edu.utp.kursy;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.StringTokenizer;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TreeModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import org.apache.log4j.Logger;
import pl.edu.utp.kursy.AcademyWindow.AcademyWindowApproveListener;
import pl.edu.utp.kursy.AccomodationWindow.AccomodationWindowApproveListener;
import pl.edu.utp.kursy.CompanyWindow.CompanyWindowApproveListener;
import pl.edu.utp.kursy.CourseCategoryWindow.CourseCategoryWindowListener;
import pl.edu.utp.kursy.CourseCategoryWindow.CourseCategoryWindowMode;
import pl.edu.utp.kursy.CourseEventWindow.CourseEventWindowListener;
import pl.edu.utp.kursy.WorkerWindow.WorkerWindowApproveListener;
import pl.edu.utp.kursy.comparators.BaseCourseComparator;
import pl.edu.utp.kursy.comparators.CompanyComparator;
import pl.edu.utp.kursy.comparators.CourseEventComparator;
import pl.edu.utp.kursy.comparators.WorkerComparator;
import pl.edu.utp.kursy.database.*;
import pl.edu.utp.kursy.pdf.InoviceCreator;

public class ApplicationGUI extends JFrameGUI implements 
                                                    CourseCategoryWindowListener, 
                                                    CompanyWindowApproveListener, 
                                                    WorkerWindowApproveListener,
                                                    CourseEventWindowListener,
                                                    AcademyWindowApproveListener,
                                                    AccomodationWindowApproveListener{
    
    private static final String COMPANY_CARD = "company_card";
    private static final String WORKER_CARD = "worker_card";
    private static final String INFO_CARD = "info_card";
    
    private static final String ACCOMODATION_MAIN_CARD = "accomodation_card";
    private static final String ACCOMODATION_INFO_CARD = "accomodation_info_card";
    
    public static final Logger logger = Logger.getLogger(ApplicationGUI.class);
    private DatabaseManager dataManager;
    private CoursesTreeModel coursesTreeModel;
    private CompaniesTreeModel companiesTreeModel;
    private CompanyInfoPanel companyInfoPanel;
    private WorkerInfoPanel workerInfoPanel;
    private AccomodationInfoPanel accomodationInfoPanel;
    private AccomodationTreeModel accomodationsTreeModel;
    private InovicesPanel inovicesPanel;
    
    public ApplicationGUI() {
        initComponents();
        setCenteredPosition();
        
        dataManager = new DatabaseManager();
        initMainTabbedPanel();
        initInovicesPanel();
        refreshCoursesTree();
        setNoCourseSelectedUI();
        initCourseEventsTable();
        initCourseCompaniesTable();
        initCourseWorkersTable();
        initWorkerCoursesTable();
        initCompanyCoursesTable();
        
        refreshCompaniesTree();
        setNoCompanySelectedUI();
        
        refreshAccomodationTree();
        setNoAccomodationSelectedUI();
        
        companyInfoPanel = new CompanyInfoPanel(null);
        workerInfoPanel = new WorkerInfoPanel(null);
        accomodationInfoPanel = new AccomodationInfoPanel(null);
        companyDetailsPanel.add(companyInfoPanel, BorderLayout.CENTER);
        workerDetailsPanel.add(workerInfoPanel, BorderLayout.CENTER);
        accomodationDetailsPanel.add(accomodationInfoPanel, BorderLayout.CENTER);
        accomodationApproveEditButton.setVisible(false);
        accomodationCancelEditButton.setVisible(false);
        setShowCompanyEditButtons(false);
        setShowWorkerEditButtons(false);
    }
    
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        mainTabbedPanel = new javax.swing.JTabbedPane();
        coursesPanel = new javax.swing.JPanel();
        coursesSplitPanel = new javax.swing.JSplitPane();
        coursesTreeScrollPanel = new javax.swing.JScrollPane();
        coursesTree = new javax.swing.JTree();
        coursePanel = new javax.swing.JPanel();
        courseDescriptionScrollPanel = new javax.swing.JScrollPane();
        courseDescriptionTextArea = new javax.swing.JTextArea();
        courseEventsScrollPanel = new javax.swing.JScrollPane();
        courseEventsTable = new javax.swing.JTable();
        addCourseEventButton = new javax.swing.JButton();
        courseCompaniesScrollPanel = new javax.swing.JScrollPane();
        courseCompaniesTable = new javax.swing.JTable();
        courseWorkersScrollPanel = new javax.swing.JScrollPane();
        courseWorkersTable = new javax.swing.JTable();
        courseCostLabel = new javax.swing.JLabel();
        jLabel1 = new javax.swing.JLabel();
        courseCostTextField = new javax.swing.JTextField();
        companiesPanel = new javax.swing.JPanel();
        companiesSplitPanel = new javax.swing.JSplitPane();
        companiesScrollPanel = new javax.swing.JScrollPane();
        companiesTree = new javax.swing.JTree();
        companyOrWorkerPanel = new javax.swing.JPanel();
        companyPanel = new javax.swing.JPanel();
        companyDetailsPanel = new javax.swing.JPanel();
        companyEditApplyButton = new javax.swing.JButton();
        companyEditCancelButton = new javax.swing.JButton();
        invoiceButton = new javax.swing.JButton();
        companiesCoursesScrollPanel = new javax.swing.JScrollPane();
        companiesCoursesTable = new javax.swing.JTable();
        workerPanel = new javax.swing.JPanel();
        workerDetailsPanel = new javax.swing.JPanel();
        workerEditApplyButton = new javax.swing.JButton();
        workerEditCancelButton = new javax.swing.JButton();
        workerCoursesScrollPanel = new javax.swing.JScrollPane();
        workerCoursesTable = new javax.swing.JTable();
        infoPanel = new javax.swing.JPanel();
        addCompanyButton = new javax.swing.JButton();
        addWorkerButton = new javax.swing.JButton();
        companiesInfoLabel = new javax.swing.JLabel();
        accomodationPanel = new javax.swing.JPanel();
        accomodationSplitPanel = new javax.swing.JSplitPane();
        accomodationContentPanel = new javax.swing.JPanel();
        accomodationMainInfoPanel = new javax.swing.JPanel();
        addAccomodationButton = new javax.swing.JButton();
        accomodationInfoLabel = new javax.swing.JLabel();
        accomodationMainPanel = new javax.swing.JPanel();
        accomodationDetailsPanel = new javax.swing.JPanel();
        accomodationCancelEditButton = new javax.swing.JButton();
        accomodationApproveEditButton = new javax.swing.JButton();
        accomodationEditButton = new javax.swing.JButton();
        accomodationDeleteButton = new javax.swing.JButton();
        accomodationTreeScrollPanel = new javax.swing.JScrollPane();
        accomodationTree = new javax.swing.JTree();
        inovicesTabPanel = new javax.swing.JPanel();
        menuBar = new javax.swing.JMenuBar();
        coursesMenu = new javax.swing.JMenu();
        addCategoryMenuItem = new javax.swing.JMenuItem();
        addCourseMenuItem = new javax.swing.JMenuItem();
        courseOperationSeparator = new javax.swing.JPopupMenu.Separator();
        editCategoryMenuItem = new javax.swing.JMenuItem();
        removeCategoryMenuItem = new javax.swing.JMenuItem();
        editCourseMenuItem = new javax.swing.JMenuItem();
        removeCourseMenuItem = new javax.swing.JMenuItem();
        courseEditOperationSeparator = new javax.swing.JPopupMenu.Separator();
        closeMenuItem = new javax.swing.JMenuItem();
        companiesMenu = new javax.swing.JMenu();
        addCompanyMenuItem = new javax.swing.JMenuItem();
        addWorkerMenuItem = new javax.swing.JMenuItem();
        companyOperationsSeparator = new javax.swing.JPopupMenu.Separator();
        editCompanyMenuItem = new javax.swing.JMenuItem();
        removeCompanyMenuItem = new javax.swing.JMenuItem();
        editWorkerMenuItem = new javax.swing.JMenuItem();
        removeWorkerMenuItem = new javax.swing.JMenuItem();
        academyMenu = new javax.swing.JMenu();
        academyDataMenuItem = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle(getString("application_name"));

        coursesSplitPanel.setDividerLocation(180);
        coursesSplitPanel.setPreferredSize(new java.awt.Dimension(728, 400));

        javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("root");
        coursesTree.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1));
        coursesTree.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
            public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
                coursesTreeValueChanged(evt);
            }
        });
        coursesTreeScrollPanel.setViewportView(coursesTree);

        coursesSplitPanel.setLeftComponent(coursesTreeScrollPanel);

        courseDescriptionTextArea.setColumns(20);
        courseDescriptionTextArea.setEditable(false);
        courseDescriptionTextArea.setRows(5);
        courseDescriptionTextArea.setBorder(javax.swing.BorderFactory.createTitledBorder(getString("description")));
        courseDescriptionScrollPanel.setViewportView(courseDescriptionTextArea);

        courseEventsScrollPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(getString("course_events")));

        courseEventsTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {},
                {},
                {},
                {}
            },
            new String [] {

            }
        ));
        courseEventsScrollPanel.setViewportView(courseEventsTable);

        addCourseEventButton.setText(getString("add_course_event"));
        addCourseEventButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addCourseEventButtonActionPerformed(evt);
            }
        });

        courseCompaniesScrollPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(getString("companies")));

        courseCompaniesTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {},
                {},
                {},
                {}
            },
            new String [] {

            }
        ));
        courseCompaniesTable.setRowHeight(32);
        courseCompaniesScrollPanel.setViewportView(courseCompaniesTable);

        courseWorkersScrollPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(getString("workers")));

        courseWorkersTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {},
                {},
                {}
            },
            new String [] {

            }
        ));
        courseWorkersScrollPanel.setViewportView(courseWorkersTable);

        courseCostLabel.setText(getString("courseCost"));

        jLabel1.setText("PLN");

        courseCostTextField.setEditable(false);
        courseCostTextField.setText("0");

        javax.swing.GroupLayout coursePanelLayout = new javax.swing.GroupLayout(coursePanel);
        coursePanel.setLayout(coursePanelLayout);
        coursePanelLayout.setHorizontalGroup(
            coursePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(courseDescriptionScrollPanel)
            .addComponent(courseEventsScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 587, Short.MAX_VALUE)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, coursePanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(courseCostLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(courseCostTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 72, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(addCourseEventButton)
                .addContainerGap())
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, coursePanelLayout.createSequentialGroup()
                .addComponent(courseCompaniesScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(courseWorkersScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 268, javax.swing.GroupLayout.PREFERRED_SIZE))
        );
        coursePanelLayout.setVerticalGroup(
            coursePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(coursePanelLayout.createSequentialGroup()
                .addComponent(courseDescriptionScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addGroup(coursePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(addCourseEventButton)
                    .addComponent(courseCostLabel)
                    .addComponent(jLabel1)
                    .addComponent(courseCostTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(8, 8, 8)
                .addComponent(courseEventsScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 148, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(coursePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(courseCompaniesScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 172, Short.MAX_VALUE)
                    .addComponent(courseWorkersScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)))
        );

        coursesSplitPanel.setRightComponent(coursePanel);

        javax.swing.GroupLayout coursesPanelLayout = new javax.swing.GroupLayout(coursesPanel);
        coursesPanel.setLayout(coursesPanelLayout);
        coursesPanelLayout.setHorizontalGroup(
            coursesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(coursesSplitPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 778, Short.MAX_VALUE)
        );
        coursesPanelLayout.setVerticalGroup(
            coursesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(coursesSplitPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 478, Short.MAX_VALUE)
        );

        mainTabbedPanel.addTab(getString("courses"), coursesPanel);

        companiesPanel.setLayout(new java.awt.BorderLayout());

        companiesSplitPanel.setDividerLocation(180);

        treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("root");
        companiesTree.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1));
        companiesTree.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
            public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
                companiesTreeValueChanged(evt);
            }
        });
        companiesScrollPanel.setViewportView(companiesTree);

        companiesSplitPanel.setLeftComponent(companiesScrollPanel);

        companyOrWorkerPanel.setLayout(new java.awt.CardLayout());

        companyDetailsPanel.setLayout(new java.awt.BorderLayout());

        companyEditApplyButton.setText(getString("save_changes"));
        companyEditApplyButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                companyEditApplyButtonActionPerformed(evt);
            }
        });

        companyEditCancelButton.setText(getString("cancel"));
        companyEditCancelButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                companyEditCancelButtonActionPerformed(evt);
            }
        });

        invoiceButton.setText(getString("get_invoice"));
        invoiceButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                invoiceButtonActionPerformed(evt);
            }
        });

        companiesCoursesTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {},
                {},
                {},
                {}
            },
            new String [] {

            }
        ));
        companiesCoursesScrollPanel.setViewportView(companiesCoursesTable);

        javax.swing.GroupLayout companyPanelLayout = new javax.swing.GroupLayout(companyPanel);
        companyPanel.setLayout(companyPanelLayout);
        companyPanelLayout.setHorizontalGroup(
            companyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(companyDetailsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(companyPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(invoiceButton, javax.swing.GroupLayout.PREFERRED_SIZE, 241, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 34, Short.MAX_VALUE)
                .addComponent(companyEditApplyButton, javax.swing.GroupLayout.PREFERRED_SIZE, 156, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(companyEditCancelButton, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
            .addGroup(companyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(companiesCoursesScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 587, Short.MAX_VALUE))
        );
        companyPanelLayout.setVerticalGroup(
            companyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(companyPanelLayout.createSequentialGroup()
                .addComponent(companyDetailsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 310, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(companyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(companyEditApplyButton)
                    .addComponent(companyEditCancelButton)
                    .addComponent(invoiceButton))
                .addGap(0, 129, Short.MAX_VALUE))
            .addGroup(companyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, companyPanelLayout.createSequentialGroup()
                    .addGap(0, 368, Short.MAX_VALUE)
                    .addComponent(companiesCoursesScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 108, javax.swing.GroupLayout.PREFERRED_SIZE)))
        );

        invoiceButton.getAccessibleContext().setAccessibleParent(this);

        companyOrWorkerPanel.add(companyPanel, "company_card");

        workerDetailsPanel.setLayout(new java.awt.BorderLayout());

        workerEditApplyButton.setText(getString("save_changes"));
        workerEditApplyButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                workerEditApplyButtonActionPerformed(evt);
            }
        });

        workerEditCancelButton.setText(getString("cancel"));
        workerEditCancelButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                workerEditCancelButtonActionPerformed(evt);
            }
        });

        workerCoursesScrollPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(getString("courses")));

        workerCoursesTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {},
                {},
                {},
                {}
            },
            new String [] {

            }
        ));
        workerCoursesScrollPanel.setViewportView(workerCoursesTable);

        javax.swing.GroupLayout workerPanelLayout = new javax.swing.GroupLayout(workerPanel);
        workerPanel.setLayout(workerPanelLayout);
        workerPanelLayout.setHorizontalGroup(
            workerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(workerDetailsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, workerPanelLayout.createSequentialGroup()
                .addContainerGap(282, Short.MAX_VALUE)
                .addComponent(workerEditApplyButton, javax.swing.GroupLayout.PREFERRED_SIZE, 160, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(workerEditCancelButton)
                .addGap(6, 6, 6))
            .addGroup(workerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(workerCoursesScrollPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 587, Short.MAX_VALUE))
        );
        workerPanelLayout.setVerticalGroup(
            workerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(workerPanelLayout.createSequentialGroup()
                .addComponent(workerDetailsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 225, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(workerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(workerEditApplyButton)
                    .addComponent(workerEditCancelButton))
                .addGap(0, 214, Short.MAX_VALUE))
            .addGroup(workerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, workerPanelLayout.createSequentialGroup()
                    .addGap(0, 281, Short.MAX_VALUE)
                    .addComponent(workerCoursesScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 195, javax.swing.GroupLayout.PREFERRED_SIZE)))
        );

        companyOrWorkerPanel.add(workerPanel, "worker_card");

        addCompanyButton.setText(getString("add_company"));
        addCompanyButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addCompanyButtonActionPerformed(evt);
            }
        });

        addWorkerButton.setText(getString("add_worker"));
        addWorkerButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addWorkerButtonActionPerformed(evt);
            }
        });

        companiesInfoLabel.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N
        companiesInfoLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        companiesInfoLabel.setText("<html>"+getString("companies_info").replace("\n", "<br/>")+"</html>");
        companiesInfoLabel.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);

        javax.swing.GroupLayout infoPanelLayout = new javax.swing.GroupLayout(infoPanel);
        infoPanel.setLayout(infoPanelLayout);
        infoPanelLayout.setHorizontalGroup(
            infoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(infoPanelLayout.createSequentialGroup()
                .addGroup(infoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(infoPanelLayout.createSequentialGroup()
                        .addGap(137, 137, 137)
                        .addGroup(infoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(addCompanyButton, javax.swing.GroupLayout.DEFAULT_SIZE, 272, Short.MAX_VALUE)
                            .addComponent(addWorkerButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addGap(0, 166, Short.MAX_VALUE))
                    .addGroup(infoPanelLayout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(companiesInfoLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                .addContainerGap())
        );
        infoPanelLayout.setVerticalGroup(
            infoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(infoPanelLayout.createSequentialGroup()
                .addGap(52, 52, 52)
                .addComponent(addCompanyButton)
                .addGap(18, 18, 18)
                .addComponent(addWorkerButton)
                .addGap(27, 27, 27)
                .addComponent(companiesInfoLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 134, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(195, Short.MAX_VALUE))
        );

        companyOrWorkerPanel.add(infoPanel, "info_card");
        infoPanel.getAccessibleContext().setAccessibleName("");

        companiesSplitPanel.setRightComponent(companyOrWorkerPanel);

        companiesPanel.add(companiesSplitPanel, java.awt.BorderLayout.CENTER);

        mainTabbedPanel.addTab(getString("companies"), companiesPanel);

        accomodationSplitPanel.setDividerLocation(180);

        accomodationContentPanel.setLayout(new java.awt.CardLayout());

        addAccomodationButton.setText(getString("accomodation_add"));
        addAccomodationButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addAccomodationButtonActionPerformed(evt);
            }
        });

        accomodationInfoLabel.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N
        accomodationInfoLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        accomodationInfoLabel.setText("<html>"+getString("accomodation_info").replace("\n", "<br/>")+"</html>");

        javax.swing.GroupLayout accomodationMainInfoPanelLayout = new javax.swing.GroupLayout(accomodationMainInfoPanel);
        accomodationMainInfoPanel.setLayout(accomodationMainInfoPanelLayout);
        accomodationMainInfoPanelLayout.setHorizontalGroup(
            accomodationMainInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(accomodationInfoLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(accomodationMainInfoPanelLayout.createSequentialGroup()
                .addContainerGap(156, Short.MAX_VALUE)
                .addComponent(addAccomodationButton, javax.swing.GroupLayout.PREFERRED_SIZE, 275, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(156, Short.MAX_VALUE))
        );
        accomodationMainInfoPanelLayout.setVerticalGroup(
            accomodationMainInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(accomodationMainInfoPanelLayout.createSequentialGroup()
                .addGap(65, 65, 65)
                .addComponent(addAccomodationButton)
                .addGap(47, 47, 47)
                .addComponent(accomodationInfoLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 181, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(158, Short.MAX_VALUE))
        );

        accomodationContentPanel.add(accomodationMainInfoPanel, "accomodation_info_card");

        accomodationDetailsPanel.setLayout(new java.awt.BorderLayout());

        accomodationCancelEditButton.setText(getString("cancel"));
        accomodationCancelEditButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                accomodationCancelEditButtonActionPerformed(evt);
            }
        });

        accomodationApproveEditButton.setText(getString("save"));
        accomodationApproveEditButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                accomodationApproveEditButtonActionPerformed(evt);
            }
        });

        accomodationEditButton.setText(getString("edit"));
        accomodationEditButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                accomodationEditButtonActionPerformed(evt);
            }
        });

        accomodationDeleteButton.setText(getString("delete"));
        accomodationDeleteButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                accomodationDeleteButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout accomodationMainPanelLayout = new javax.swing.GroupLayout(accomodationMainPanel);
        accomodationMainPanel.setLayout(accomodationMainPanelLayout);
        accomodationMainPanelLayout.setHorizontalGroup(
            accomodationMainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(accomodationDetailsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, accomodationMainPanelLayout.createSequentialGroup()
                .addContainerGap(31, Short.MAX_VALUE)
                .addComponent(accomodationEditButton, javax.swing.GroupLayout.PREFERRED_SIZE, 121, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(accomodationDeleteButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(accomodationApproveEditButton)
                .addGap(18, 18, 18)
                .addComponent(accomodationCancelEditButton)
                .addContainerGap())
        );
        accomodationMainPanelLayout.setVerticalGroup(
            accomodationMainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(accomodationMainPanelLayout.createSequentialGroup()
                .addComponent(accomodationDetailsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 433, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(accomodationMainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(accomodationCancelEditButton)
                    .addComponent(accomodationApproveEditButton)
                    .addComponent(accomodationEditButton)
                    .addComponent(accomodationDeleteButton))
                .addGap(0, 6, Short.MAX_VALUE))
        );

        accomodationContentPanel.add(accomodationMainPanel, "accomodation_card");

        accomodationSplitPanel.setRightComponent(accomodationContentPanel);

        treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("root");
        accomodationTree.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1));
        accomodationTree.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
            public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
                accomodationTreeValueChanged(evt);
            }
        });
        accomodationTreeScrollPanel.setViewportView(accomodationTree);

        accomodationSplitPanel.setLeftComponent(accomodationTreeScrollPanel);

        javax.swing.GroupLayout accomodationPanelLayout = new javax.swing.GroupLayout(accomodationPanel);
        accomodationPanel.setLayout(accomodationPanelLayout);
        accomodationPanelLayout.setHorizontalGroup(
            accomodationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(accomodationSplitPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 778, Short.MAX_VALUE)
        );
        accomodationPanelLayout.setVerticalGroup(
            accomodationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(accomodationSplitPanel)
        );

        mainTabbedPanel.addTab(getString("accomodation_base"), accomodationPanel);

        inovicesTabPanel.setLayout(new java.awt.BorderLayout());
        mainTabbedPanel.addTab(getString("issued_inovices"), inovicesTabPanel);

        getContentPane().add(mainTabbedPanel, java.awt.BorderLayout.CENTER);

        coursesMenu.setText(getString("application_name"));

        addCategoryMenuItem.setText(getString("add_category"));
        addCategoryMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addCategoryMenuItemActionPerformed(evt);
            }
        });
        coursesMenu.add(addCategoryMenuItem);

        addCourseMenuItem.setText(getString("add_course"));
        addCourseMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addCourseMenuItemActionPerformed(evt);
            }
        });
        coursesMenu.add(addCourseMenuItem);
        coursesMenu.add(courseOperationSeparator);

        editCategoryMenuItem.setText(getString("edit_category"));
        editCategoryMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                editCategoryMenuItemActionPerformed(evt);
            }
        });
        coursesMenu.add(editCategoryMenuItem);

        removeCategoryMenuItem.setText(getString("remove_category"));
        removeCategoryMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeCategoryMenuItemActionPerformed(evt);
            }
        });
        coursesMenu.add(removeCategoryMenuItem);

        editCourseMenuItem.setText(getString("edit_course"));
        editCourseMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                editCourseMenuItemActionPerformed(evt);
            }
        });
        coursesMenu.add(editCourseMenuItem);

        removeCourseMenuItem.setText(getString("remove_course"));
        removeCourseMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeCourseMenuItemActionPerformed(evt);
            }
        });
        coursesMenu.add(removeCourseMenuItem);
        coursesMenu.add(courseEditOperationSeparator);

        closeMenuItem.setText(getString("close"));
        closeMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closeMenuItemActionPerformed(evt);
            }
        });
        coursesMenu.add(closeMenuItem);

        menuBar.add(coursesMenu);

        companiesMenu.setText(getString("companies"));

        addCompanyMenuItem.setText(getString("add_company"));
        addCompanyMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addCompanyMenuItemActionPerformed(evt);
            }
        });
        companiesMenu.add(addCompanyMenuItem);

        addWorkerMenuItem.setText(getString("add_worker"));
        addWorkerMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addWorkerMenuItemActionPerformed(evt);
            }
        });
        companiesMenu.add(addWorkerMenuItem);
        companiesMenu.add(companyOperationsSeparator);

        editCompanyMenuItem.setText(getString("edit_company"));
        editCompanyMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                editCompanyMenuItemActionPerformed(evt);
            }
        });
        companiesMenu.add(editCompanyMenuItem);

        removeCompanyMenuItem.setText(getString("remove_company"));
        removeCompanyMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeCompanyMenuItemActionPerformed(evt);
            }
        });
        companiesMenu.add(removeCompanyMenuItem);

        editWorkerMenuItem.setText(getString("edit_worker"));
        editWorkerMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                editWorkerMenuItemActionPerformed(evt);
            }
        });
        companiesMenu.add(editWorkerMenuItem);

        removeWorkerMenuItem.setText(getString("remove_worker"));
        removeWorkerMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeWorkerMenuItemActionPerformed(evt);
            }
        });
        companiesMenu.add(removeWorkerMenuItem);

        menuBar.add(companiesMenu);

        academyMenu.setText(getString("academy"));

        academyDataMenuItem.setText(getString("academy_data"));
        academyDataMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                academyDataMenuItemActionPerformed(evt);
            }
        });
        academyMenu.add(academyDataMenuItem);

        menuBar.add(academyMenu);

        setJMenuBar(menuBar);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void closeMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeMenuItemActionPerformed
        logger.info("Closing application...");
        System.exit(0);
    }//GEN-LAST:event_closeMenuItemActionPerformed

    private void coursesTreeValueChanged(javax.swing.event.TreeSelectionEvent evt) {//GEN-FIRST:event_coursesTreeValueChanged
        TreePath leadPath = evt.getNewLeadSelectionPath();
        if(leadPath != null){
            Object lastPath = leadPath.getLastPathComponent();
            if(lastPath instanceof BaseCourse){
                BaseCourse course = (BaseCourse)evt.getNewLeadSelectionPath().getLastPathComponent();
                setCourseDescriptionText(course.getDescription());
                if(lastPath instanceof CourseCategory){
                    setCategorySelectedUI((CourseCategory)lastPath);
                    showCourseEvents(null);
                }else if(lastPath instanceof Course){
                    setCourseSelectedUI((Course)lastPath);
                    showCourseEvents((Course)lastPath);
                    Course c = (Course) course;
                    setCourseCostText(String.valueOf(c.getCost()));
                }
                
            }else{
                setCourseDescriptionText("");
                setCourseCostText("");
                setNoCourseSelectedUI();
                showCourseEvents(null);
            }
        }
//        else{
//            setCourseDescriptionText("");
//            setNoCourseSelectedUI();
//        }
    }//GEN-LAST:event_coursesTreeValueChanged
   
    private void initMainTabbedPanel(){
        mainTabbedPanel.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                if(mainTabbedPanel.getSelectedIndex() == 2){
                    if(inovicesPanel != null){
                        inovicesPanel.refresh();
                    }
                }
            }
        });
    }
    
    private void initInovicesPanel(){
        inovicesPanel = new InovicesPanel(dataManager);
        inovicesTabPanel.add(inovicesPanel, BorderLayout.CENTER);
        inovicesPanel.refresh();
    }
    
    
    private void initCourseEventsTable(){
        courseEventsTable.addMouseListener(new MouseAdapter(){
            @Override
            public void mouseClicked(MouseEvent e) {
                CourseEvent event = getCurrentSelectedCourseEvent();
                if(event != null){
                    if(e.getClickCount() == 2){
                        showCourseEventWindow(event);
                    }else{
                        showCourseEventsStudents(event);
                    }
                }
            }
        });
        courseEventsTable.setAutoCreateRowSorter(true);
        courseEventsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        courseEventsTable.setDefaultRenderer(Object.class, new ExpiredCellRenderer());
        showCourseEvents(null);
    }
    

    
    private void initCourseCompaniesTable(){
        //courseCompaniesTable.setAutoCreateRowSorter(true);
        courseCompaniesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        courseCompaniesTable.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                Company company = getCurrentSelectedCourseCompany();
                CourseEvent event = getCurrentSelectedCourseEvent();
                if(company != null && event != null){
                    showCourseCompanyWorkers(company, event);
                }
            }
        });
    }
    
    private void initCourseWorkersTable(){
        courseWorkersTable.setAutoCreateRowSorter(true);
       
    }
    
    private void initWorkerCoursesTable(){
        workerCoursesTable.setAutoCreateRowSorter(true);
        workerCoursesTable.setDefaultRenderer(Object.class, new ExpiredCellRenderer());
    }
    
    private void initCompanyCoursesTable(){
        companiesCoursesTable.setAutoCreateRowSorter(true);
        companiesCoursesTable.setDefaultRenderer(Object.class, new ExpiredCellRenderer());
    }
    
    private CourseEvent getCurrentSelectedCourseEvent(){
        CourseEvent event = null;
        CourseEventsTableModel model = (CourseEventsTableModel)courseEventsTable.getModel();
        int selectedRow = courseEventsTable.getSelectedRow();
        if(selectedRow >= 0){
            event = model.getCourseEventAt(selectedRow);
        }
        return event;
    }
    
    private Company getCurrentSelectedCourseCompany(){
        Company company = null;
        CourseCompaniesTableModel courseCompaniesTableModel = (CourseCompaniesTableModel)courseCompaniesTable.getModel();
        int selectedRow = courseCompaniesTable.getSelectedRow();
        if(selectedRow >= 0){
            company = courseCompaniesTableModel.getCompanyAt(selectedRow);
        }
        return company;
    }
    
    private void setNoCourseSelectedUI(){
        editCategoryMenuItem.setVisible(false);
        removeCategoryMenuItem.setVisible(false);
        editCourseMenuItem.setVisible(false);
        removeCourseMenuItem.setVisible(false);
        courseEditOperationSeparator.setVisible(false);
    }
    
    private void setCategorySelectedUI(CourseCategory category){
        editCategoryMenuItem.setVisible(true);
        removeCategoryMenuItem.setVisible(true);
        editCourseMenuItem.setVisible(false);
        removeCourseMenuItem.setVisible(false);
        courseEditOperationSeparator.setVisible(true);
    }
    
    private void setCourseSelectedUI(Course course){
        editCategoryMenuItem.setVisible(false);
        removeCategoryMenuItem.setVisible(false);
        editCourseMenuItem.setVisible(true);
        removeCourseMenuItem.setVisible(true);
        courseEditOperationSeparator.setVisible(true);
    }
    
    private void showCourseEvents(Course course){
        ArrayList<CourseEvent> events;
        if(course == null){
            events = new ArrayList<>();
        } else{
            events = new ArrayList<>(course.getCourseEvents());
        }
        sortCourseEvents(events);
        courseEventsTable.setModel(new CourseEventsTableModel(events));
        courseEventsTable.repaint();
        showCourseEventsStudents(null);
        showCourseCompanyWorkers(null, null);
    }
    
    private void sortCourseEvents(ArrayList<CourseEvent> events){
        Collections.sort(events, new CourseEventComparator());
    }
    
    private void showCourseEventsStudents(CourseEvent event){
        ArrayList<Company> companies;
        
        if(event == null){
            companies = new ArrayList<>();
        } else{
            companies = new ArrayList<>(event.getCompanies());
        }
        sortCompanies(companies);
        courseCompaniesTable.setModel(new CourseCompaniesTableModel(companies));

        Action action = new AbstractAction(){
            @Override
            public void actionPerformed(ActionEvent e) {
               openDocumentsWindow();
            }
        };
        new ButtonColumn(courseCompaniesTable, action, 1);
        courseCompaniesTable.repaint();
    }
    
    private void openDocumentsWindow(){
        Company company = getCurrentSelectedCourseCompany();
        CourseEvent courseEvent = getCurrentSelectedCourseEvent();
        DocumentsWindow docsWindow = new DocumentsWindow(dataManager, company, courseEvent);
        docsWindow.setVisible(true);
        
    }
        
    private void showCourseCompanyWorkers(Company company, CourseEvent event){
        ArrayList<Worker> workers = new ArrayList<>();
        
        if(company != null){
            ArrayList<Worker> cWorkers = new ArrayList<>(company.getWorkers());
            ArrayList<Worker> eWorkers = new ArrayList<>(event.getWorkers());
            
            for(Worker eWorker: eWorkers){
                for(Worker cWorker: cWorkers){
                    if(eWorker.getId() == cWorker.getId()){
                        workers.add(cWorker);
                    }
                }
            }
        }
        sortWorkers(workers);
        courseWorkersTable.setModel(new CourseWorkersTableModel(workers));
        courseWorkersTable.repaint();
    }
    
    private void addCategoryMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addCategoryMenuItemActionPerformed
        CourseCategoryWindow ccw = new CourseCategoryWindow(null, CourseCategoryWindowMode.ADD_CATEGORY, this);
        ccw.setVisible(true);
    }//GEN-LAST:event_addCategoryMenuItemActionPerformed

    private void addCourseMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addCourseMenuItemActionPerformed
        CourseCategoryWindow ccw = new CourseCategoryWindow(null, CourseCategoryWindowMode.ADD_COURSE, this);
        ccw.setVisible(true);
    }//GEN-LAST:event_addCourseMenuItemActionPerformed

    private void editCategoryMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editCategoryMenuItemActionPerformed
        CourseCategory category = (CourseCategory)coursesTree.getSelectionPath().getLastPathComponent();
        CourseCategoryWindow ccw = new CourseCategoryWindow(category, CourseCategoryWindowMode.EDIT_CATEGORY, this);
        ccw.setVisible(true);
    }//GEN-LAST:event_editCategoryMenuItemActionPerformed

    private void removeCategoryMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeCategoryMenuItemActionPerformed
        CourseCategory category = (CourseCategory)coursesTree.getSelectionPath().getLastPathComponent();
        if(showCourseRemoveConfirmationDialog(category) == JOptionPane.YES_OPTION){
            dataManager.deleteCourseCategory(category);
            refreshCoursesTree();
        }
    }//GEN-LAST:event_removeCategoryMenuItemActionPerformed

    private void editCourseMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editCourseMenuItemActionPerformed
        Course course = (Course)coursesTree.getSelectionPath().getLastPathComponent();
        CourseCategoryWindow ccw = new CourseCategoryWindow(course, CourseCategoryWindowMode.EDIT_COURSE, this);
        ccw.setVisible(true);
    }//GEN-LAST:event_editCourseMenuItemActionPerformed

    private void removeCourseMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeCourseMenuItemActionPerformed
        Course course = (Course)coursesTree.getSelectionPath().getLastPathComponent();
        if(showCourseRemoveConfirmationDialog(course) == JOptionPane.YES_OPTION){
            dataManager.deleteCourse(course);
            refreshCoursesTree();
        }
    }//GEN-LAST:event_removeCourseMenuItemActionPerformed

    private void addCourseEventButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addCourseEventButtonActionPerformed
        showCourseEventWindow(null); 
    }//GEN-LAST:event_addCourseEventButtonActionPerformed

    private void addCompanyMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addCompanyMenuItemActionPerformed
        showAddCompanyWindow();
    }//GEN-LAST:event_addCompanyMenuItemActionPerformed

    private void addWorkerMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addWorkerMenuItemActionPerformed
        showAddWorkerWindow();
    }//GEN-LAST:event_addWorkerMenuItemActionPerformed

    private void editCompanyMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editCompanyMenuItemActionPerformed
        companyInfoPanel.setEditableMode(true);
        setShowCompanyEditButtons(true);
    }//GEN-LAST:event_editCompanyMenuItemActionPerformed

    private void removeCompanyMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeCompanyMenuItemActionPerformed
        Company company = (Company)companiesTree.getSelectionPath().getLastPathComponent();
        if(showCompanyRemoveConfirmationDialog(company) == JOptionPane.YES_OPTION){
            dataManager.deleteCompany(company);
            refreshCompaniesTree();
        }
    }//GEN-LAST:event_removeCompanyMenuItemActionPerformed

    private void editWorkerMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editWorkerMenuItemActionPerformed
        workerInfoPanel.setEditableMode(true);
        setShowWorkerEditButtons(true);
    }//GEN-LAST:event_editWorkerMenuItemActionPerformed

    private void removeWorkerMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeWorkerMenuItemActionPerformed
        Worker worker = (Worker)companiesTree.getSelectionPath().getLastPathComponent();
        if(showWorkerRemoveConfirmationDialog(worker) == JOptionPane.YES_OPTION){
            dataManager.deleteWorker(worker);
            refreshCompaniesTree();
        }
    }//GEN-LAST:event_removeWorkerMenuItemActionPerformed

    private void companiesTreeValueChanged(javax.swing.event.TreeSelectionEvent evt) {//GEN-FIRST:event_companiesTreeValueChanged
        TreePath leadPath = evt.getNewLeadSelectionPath();
        if(leadPath != null){
            Object lastPath = leadPath.getLastPathComponent();
            if(lastPath instanceof Company){
                Company company = (Company)lastPath;
                setCompanySelectedUI(company);
            }else if(lastPath instanceof Worker){
                Worker worker = (Worker)lastPath;
                setWorkerSelectedUI(worker);
            }else{
                setNoCompanySelectedUI();
            }
        }else{
            setNoCompanySelectedUI();
        }
    }//GEN-LAST:event_companiesTreeValueChanged

    private void addCompanyButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addCompanyButtonActionPerformed
        showAddCompanyWindow();
    }//GEN-LAST:event_addCompanyButtonActionPerformed

    private void addWorkerButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addWorkerButtonActionPerformed
        showAddWorkerWindow();
    }//GEN-LAST:event_addWorkerButtonActionPerformed

    private void companyEditApplyButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_companyEditApplyButtonActionPerformed
        Company company = companyInfoPanel.getCompany();
        if(company != null){
            dataManager.updateCompany(company);
            refreshCompaniesTree();
            setShowCompanyEditButtons(false);
            companyInfoPanel.setEditableMode(false);
        }
    }//GEN-LAST:event_companyEditApplyButtonActionPerformed

    private void companyEditCancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_companyEditCancelButtonActionPerformed
        setShowCompanyEditButtons(false);
        companyInfoPanel.setEditableMode(false);
    }//GEN-LAST:event_companyEditCancelButtonActionPerformed

    private void invoiceButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_invoiceButtonActionPerformed
        Company company = companyInfoPanel.getCompany();
        InoviceCreator creator = new InoviceCreator(dataManager, company, null);
        creator.saveInoviceInDatabase();
        creator.createPDF();

    }//GEN-LAST:event_invoiceButtonActionPerformed

    private void workerEditCancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_workerEditCancelButtonActionPerformed
        setShowWorkerEditButtons(false);
        workerInfoPanel.setEditableMode(false);
    }//GEN-LAST:event_workerEditCancelButtonActionPerformed

    private void workerEditApplyButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_workerEditApplyButtonActionPerformed
        Worker worker = workerInfoPanel.getWorker();
        if(worker != null){
            dataManager.updateWorker(worker);
            refreshCompaniesTree();
            setShowWorkerEditButtons(false);
            workerInfoPanel.setEditableMode(false);
        }
    }//GEN-LAST:event_workerEditApplyButtonActionPerformed

    private void academyDataMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_academyDataMenuItemActionPerformed
        
        Academy academy = dataManager.getAcademy();
        AcademyWindow academyWindow = new AcademyWindow(academy);
        academyWindow.setApproveListener(this);
        academyWindow.setVisible(true);
        
    }//GEN-LAST:event_academyDataMenuItemActionPerformed

    private void addAccomodationButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addAccomodationButtonActionPerformed
        AccomodationWindow accomodationWindow = new AccomodationWindow();
        accomodationWindow.setAccomodationWindowApproveListener(this);
        accomodationWindow.setVisible(true);
    }//GEN-LAST:event_addAccomodationButtonActionPerformed

    private void accomodationTreeValueChanged(javax.swing.event.TreeSelectionEvent evt) {//GEN-FIRST:event_accomodationTreeValueChanged
        
        TreePath leadPath = evt.getNewLeadSelectionPath();
        if(leadPath != null){
            Object lastPath = leadPath.getLastPathComponent();
            if(lastPath instanceof Accomodation){
                Accomodation accomodation = (Accomodation)evt.getNewLeadSelectionPath().getLastPathComponent();
                setAccomodationSelectedUI(accomodation);
            }else{
                setNoAccomodationSelectedUI();
            }
        }
        
    }//GEN-LAST:event_accomodationTreeValueChanged

    private void accomodationEditButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_accomodationEditButtonActionPerformed
        setAccomodationEditMode(true);
    }//GEN-LAST:event_accomodationEditButtonActionPerformed

    private void accomodationApproveEditButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_accomodationApproveEditButtonActionPerformed
        dataManager.updateAccomodation(accomodationInfoPanel.getAccomodation());
        refreshAccomodationTree();
    }//GEN-LAST:event_accomodationApproveEditButtonActionPerformed

    private void accomodationCancelEditButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_accomodationCancelEditButtonActionPerformed
        setAccomodationEditMode(false);
    }//GEN-LAST:event_accomodationCancelEditButtonActionPerformed

    private void accomodationDeleteButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_accomodationDeleteButtonActionPerformed
        dataManager.deleteAccomodation(accomodationInfoPanel.getAccomodation());
        refreshAccomodationTree();
    }//GEN-LAST:event_accomodationDeleteButtonActionPerformed
    
    private void setShowCompanyEditButtons(boolean isVisible){
        companyEditApplyButton.setVisible(isVisible);
        companyEditCancelButton.setVisible(isVisible);
        invoiceButton.setVisible(!isVisible);
    }
    
    private void setShowWorkerEditButtons(boolean isVisible){
        workerEditApplyButton.setVisible(isVisible);
        workerEditCancelButton.setVisible(isVisible);
    }
    
    private void showAddCompanyWindow(){
        CompanyWindow companyWindow = new CompanyWindow(this);
        companyWindow.setVisible(true);
    }
    
    private void showAddWorkerWindow(){
        WorkerWindow workerWindow = new WorkerWindow(this);
        workerWindow.setVisible(true);
    }
    
    private void showCourseEventWindow(CourseEvent event){
        if(coursesTree.getSelectionPath() == null){
            JOptionPane.showMessageDialog(this, getString("course_not_selected_message"), 
                                                getString("course_not_selected_title"),
                                                JOptionPane.WARNING_MESSAGE);
        }else{
            Course course = (Course)coursesTree.getSelectionPath().getLastPathComponent();
            CourseEventWindow courseEventWindow = new CourseEventWindow(event, course, dataManager.getAcademy(), this);
            courseEventWindow.setVisible(true);
        }
    }
    
    @Override
    public void onCompanyWindowApprove(Company company) {
        if(company != null){
            dataManager.addCompany(company);
        }
        refreshCompaniesTree();
        
    }
    
    @Override
    public void onWorkerWindowApprove(Worker worker) {
        if(worker != null){
            dataManager.addWorker(worker);
        }
        refreshCompaniesTree();
    }
    
    @Override
    public void onCourseEventWindowApprove(CourseEvent event, CourseEventWindow.CourseEventWindowMode mode) {
        
        switch(mode){
            case ADD:
                dataManager.addCourseEvent(event);
                for(CourseEventCompanyAccomodation ceca : event.getCourseEventsCompanyAccomodation()){
                    dataManager.addCourseEventCompanyAccomodation(ceca);
                }
                break;
            case EDIT:
                CourseEvent cEvent = dataManager.getCourseEvent(event.getId());
                for(CourseEventCompanyAccomodation ceca : cEvent.getCourseEventsCompanyAccomodation()){
                    dataManager.deleteCourseEventCompanyAccomodation(ceca);
                }
                dataManager.updateCourseEvent(event);
                for(CourseEventCompanyAccomodation ceca : event.getCourseEventsCompanyAccomodation()){
                    dataManager.addCourseEventCompanyAccomodation(ceca);
                }
                break;
        }
        refreshCoursesTree();
        refreshCompaniesTree();
    }
    
    @Override
    public void onCourseEventWindowDelete(CourseEvent event){
        dataManager.deleteCourseEvent(event);
        refreshCoursesTree();
        refreshCompaniesTree();
    }
    
    private void setNoCompanySelectedUI(){
        companyOperationsSeparator.setVisible(false);
        editCompanyMenuItem.setVisible(false);
        removeCompanyMenuItem.setVisible(false);
        editWorkerMenuItem.setVisible(false);
        removeWorkerMenuItem.setVisible(false);
        showCard(INFO_CARD);

    }
    
    private void setCompanySelectedUI(Company company){        
        companyOperationsSeparator.setVisible(true);
        editCompanyMenuItem.setVisible(true);
        removeCompanyMenuItem.setVisible(true);
        editWorkerMenuItem.setVisible(false);
        removeWorkerMenuItem.setVisible(false);
        showCard(COMPANY_CARD);
        companyInfoPanel.setCompany(company);
        
        companiesCoursesTable.setModel(new WorkerCompanyCoursesTableModel(new ArrayList<CourseEvent>(company.getCourseEvents())));
        companiesCoursesTable.repaint();
    }
    
    private void setWorkerSelectedUI(Worker worker){
        companyOperationsSeparator.setVisible(true);
        editCompanyMenuItem.setVisible(false);
        removeCompanyMenuItem.setVisible(false);
        editWorkerMenuItem.setVisible(true);
        removeWorkerMenuItem.setVisible(true);
        showCard(WORKER_CARD);
        workerInfoPanel.setWorker(worker);
        
        workerCoursesTable.setModel(new WorkerCompanyCoursesTableModel(new ArrayList<CourseEvent>(worker.getCourseEvents())));
        workerCoursesTable.repaint();
    }
    
    private void showCard(String cardName){
        CardLayout cardLayout = (CardLayout)(companyOrWorkerPanel.getLayout());
        cardLayout.show(companyOrWorkerPanel, cardName);
    }
    
    private void setNoAccomodationSelectedUI(){
        showAccomodationCard(ACCOMODATION_INFO_CARD);
        setAccomodationEditMode(false);
    }
    
    private void setAccomodationSelectedUI(Accomodation accomodation){
        showAccomodationCard(ACCOMODATION_MAIN_CARD);
        accomodationInfoPanel.setAccomodation(accomodation);
        setAccomodationEditMode(false);
    }
    
    private void setAccomodationEditMode(boolean edit){
        accomodationApproveEditButton.setVisible(edit);
        accomodationCancelEditButton.setVisible(edit);
        accomodationDeleteButton.setVisible(!edit);
        accomodationEditButton.setVisible(!edit);
        if(accomodationInfoPanel != null)
            accomodationInfoPanel.setEditableMode(edit);
    }
    
    
    private void showAccomodationCard(String cardName){
        CardLayout cardLayout = (CardLayout)(accomodationContentPanel.getLayout());
        cardLayout.show(accomodationContentPanel, cardName);
    }
    
    private int showCourseRemoveConfirmationDialog(BaseCourse course){
        String title = "";
        String msg = "";
        if(course instanceof CourseCategory){
            title = String.format(getString("remove_category_confirmation_title"), course.getName());
            msg = String.format(getString("remove_category_confirmation_msg"), course.getName());
        }else if(course instanceof Course){
            title = String.format(getString("remove_course_confirmation_title"), course.getName());
            msg = String.format(getString("remove_course_confirmation_msg"), course.getName());
        }
        return JOptionPane.showConfirmDialog(this, msg, title, JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);    
    }
    
    private int showCompanyRemoveConfirmationDialog(Company company){
        String title = String.format(getString("remove_company_confirmation_title"), company.getName());
        String msg = String.format(getString("remove_company_confirmation_msg"), company.getName());
        return JOptionPane.showConfirmDialog(this, msg, title, JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); 
    }
    
    private int showWorkerRemoveConfirmationDialog(Worker worker){
        String title = String.format(getString("remove_worker_confirmation_title"), worker.getSurname(), worker.getName());
        String msg = String.format(getString("remove_worker_confirmation_msg"), worker.getSurname(), worker.getName());
        return JOptionPane.showConfirmDialog(this, msg, title, JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); 
    
    }
    
    @Override
    public void onCourseCategoryWindowApprove(BaseCourse course, CourseCategoryWindowMode mode) {
        switch(mode){
            case ADD_CATEGORY:
                dataManager.addCourseCategory((CourseCategory)course);
                break;
            case EDIT_CATEGORY:
                dataManager.updateCourseCategory((CourseCategory)course);
                break;
            case ADD_COURSE:
                dataManager.addCourse((Course)course);
                break;
            case EDIT_COURSE:
                dataManager.updateCourse((Course)course);
                break;
        }
        refreshCoursesTree();
        refreshCompaniesTree();
    }
    
    private void refreshCoursesTree(){
        
        showCourseEvents(null);
        String state = TreeUtil.getExpansionState(coursesTree, 0);
        int selectedRows[] = coursesTree.getSelectionRows();
        
        ArrayList<CourseCategory> categories = dataManager.getCourseCategories();
        sortCategories(categories);
        
        coursesTreeModel = new CoursesTreeModel(categories);
        coursesTree.setModel(coursesTreeModel);
        coursesTree.repaint();
        
        TreeUtil.restoreExpanstionState(coursesTree, 0, state);
        coursesTree.setSelectionRows(selectedRows);
    }
    
    private void sortCategories(ArrayList<CourseCategory> categories){
        Collections.sort(categories, new BaseCourseComparator());
    }
    
    private void sortCourses(ArrayList<Course> courses){
        Collections.sort(courses, new BaseCourseComparator());
    }
    
    private void refreshCompaniesTree(){
        setNoCompanySelectedUI();
        String state = TreeUtil.getExpansionState(companiesTree, 0);
        int selectedRows[] = companiesTree.getSelectionRows();
        
        ArrayList<Company> companies = dataManager.getAllCompanies();
        sortCompanies(companies);
        companiesTreeModel = new CompaniesTreeModel(companies);
        companiesTree.setModel(companiesTreeModel);
        companiesTree.repaint();
        
        TreeUtil.restoreExpanstionState(companiesTree, 0, state);
        companiesTree.setSelectionRows(selectedRows);
    }
    
    private void refreshAccomodationTree(){
        setNoAccomodationSelectedUI();
        String state = TreeUtil.getExpansionState(accomodationTree, 0);
        int selectedRows[] = accomodationTree.getSelectionRows();
        
        ArrayList<Accomodation> accomodations = dataManager.getAllAccomodations();
        
        accomodationsTreeModel = new AccomodationTreeModel(accomodations);
        accomodationTree.setModel(accomodationsTreeModel);
        accomodationTree.repaint();
        
        TreeUtil.restoreExpanstionState(accomodationTree, 0, state);
        accomodationTree.setSelectionRows(selectedRows);
    }
    
    private void sortCompanies(ArrayList<Company> companies){
        Collections.sort(companies, new CompanyComparator());
    }
    
    private void sortWorkers(ArrayList<Worker> workers){
        Collections.sort(workers, new WorkerComparator());
    }
    
    private void setCourseDescriptionText(String description){
        courseDescriptionTextArea.setText(description);
    }
    
    private void setCourseCostText(String cost){
        courseCostTextField.setText(cost);
    }
        
   
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem academyDataMenuItem;
    private javax.swing.JMenu academyMenu;
    private javax.swing.JButton accomodationApproveEditButton;
    private javax.swing.JButton accomodationCancelEditButton;
    private javax.swing.JPanel accomodationContentPanel;
    private javax.swing.JButton accomodationDeleteButton;
    private javax.swing.JPanel accomodationDetailsPanel;
    private javax.swing.JButton accomodationEditButton;
    private javax.swing.JLabel accomodationInfoLabel;
    private javax.swing.JPanel accomodationMainInfoPanel;
    private javax.swing.JPanel accomodationMainPanel;
    private javax.swing.JPanel accomodationPanel;
    private javax.swing.JSplitPane accomodationSplitPanel;
    private javax.swing.JTree accomodationTree;
    private javax.swing.JScrollPane accomodationTreeScrollPanel;
    private javax.swing.JButton addAccomodationButton;
    private javax.swing.JMenuItem addCategoryMenuItem;
    private javax.swing.JButton addCompanyButton;
    private javax.swing.JMenuItem addCompanyMenuItem;
    private javax.swing.JButton addCourseEventButton;
    private javax.swing.JMenuItem addCourseMenuItem;
    private javax.swing.JButton addWorkerButton;
    private javax.swing.JMenuItem addWorkerMenuItem;
    private javax.swing.JMenuItem closeMenuItem;
    private javax.swing.JScrollPane companiesCoursesScrollPanel;
    private javax.swing.JTable companiesCoursesTable;
    private javax.swing.JLabel companiesInfoLabel;
    private javax.swing.JMenu companiesMenu;
    private javax.swing.JPanel companiesPanel;
    private javax.swing.JScrollPane companiesScrollPanel;
    private javax.swing.JSplitPane companiesSplitPanel;
    private javax.swing.JTree companiesTree;
    private javax.swing.JPanel companyDetailsPanel;
    private javax.swing.JButton companyEditApplyButton;
    private javax.swing.JButton companyEditCancelButton;
    private javax.swing.JPopupMenu.Separator companyOperationsSeparator;
    private javax.swing.JPanel companyOrWorkerPanel;
    private javax.swing.JPanel companyPanel;
    private javax.swing.JScrollPane courseCompaniesScrollPanel;
    private javax.swing.JTable courseCompaniesTable;
    private javax.swing.JLabel courseCostLabel;
    private javax.swing.JTextField courseCostTextField;
    private javax.swing.JScrollPane courseDescriptionScrollPanel;
    private javax.swing.JTextArea courseDescriptionTextArea;
    private javax.swing.JPopupMenu.Separator courseEditOperationSeparator;
    private javax.swing.JScrollPane courseEventsScrollPanel;
    private javax.swing.JTable courseEventsTable;
    private javax.swing.JPopupMenu.Separator courseOperationSeparator;
    private javax.swing.JPanel coursePanel;
    private javax.swing.JScrollPane courseWorkersScrollPanel;
    private javax.swing.JTable courseWorkersTable;
    private javax.swing.JMenu coursesMenu;
    private javax.swing.JPanel coursesPanel;
    private javax.swing.JSplitPane coursesSplitPanel;
    private javax.swing.JTree coursesTree;
    private javax.swing.JScrollPane coursesTreeScrollPanel;
    private javax.swing.JMenuItem editCategoryMenuItem;
    private javax.swing.JMenuItem editCompanyMenuItem;
    private javax.swing.JMenuItem editCourseMenuItem;
    private javax.swing.JMenuItem editWorkerMenuItem;
    private javax.swing.JPanel infoPanel;
    private javax.swing.JPanel inovicesTabPanel;
    private javax.swing.JButton invoiceButton;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JTabbedPane mainTabbedPanel;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JMenuItem removeCategoryMenuItem;
    private javax.swing.JMenuItem removeCompanyMenuItem;
    private javax.swing.JMenuItem removeCourseMenuItem;
    private javax.swing.JMenuItem removeWorkerMenuItem;
    private javax.swing.JScrollPane workerCoursesScrollPanel;
    private javax.swing.JTable workerCoursesTable;
    private javax.swing.JPanel workerDetailsPanel;
    private javax.swing.JButton workerEditApplyButton;
    private javax.swing.JButton workerEditCancelButton;
    private javax.swing.JPanel workerPanel;
    // End of variables declaration//GEN-END:variables

    @Override
    public void onAcademyWindowApproved(Academy academy) {
        if(dataManager.getAcademy() == null){
            dataManager.addAcademy(academy);
        }else{
            dataManager.updateAcademy(academy);
        }
    }

    @Override
    public void onAccomodationWindowApprove(Accomodation accomodation) {
        dataManager.addAccomodation(accomodation);
        refreshAccomodationTree();
    }
   
    private class CoursesTreeModel implements TreeModel{
        
        private ArrayList<? extends BaseCourse> courses;
        private ArrayList<TreeModelListener> listeners;
        
        public CoursesTreeModel(ArrayList<? extends BaseCourse> courses){
            this.courses = courses;
            listeners = new ArrayList<>();
        }

        @Override
        public Object getRoot() {
            return getString("courses");
        }

        @Override
        public Object getChild(Object parent, int index) {
            if(parent.equals(getRoot())){
                return courses.get(index);
            } else if(parent instanceof CourseCategory){
                CourseCategory category = (CourseCategory)parent;
                ArrayList<Course> c = new ArrayList<>(category.getCourses());
                sortCourses(c);
                return c.get(index);
            }
            return null;
        }

        @Override
        public int getChildCount(Object parent) {
            if(parent.equals(getRoot())){
                return courses.size();
            } else if(parent instanceof CourseCategory){
                CourseCategory category = (CourseCategory)parent;
                if(category.getCourses() != null && category.getCourses().size() > 0){
                    return category.getCourses().size();
                }
            }
            return 0;
        }

        @Override
        public boolean isLeaf(Object node) {
            if(node instanceof CourseCategory){
                CourseCategory category = (CourseCategory)node;
                if(category.getCourses() != null && category.getCourses().size() > 0){
                    return false;
                }
            } else if(node.equals(getRoot())){
                return false;
            }
            return true;
        }

        @Override
        public void valueForPathChanged(TreePath path, Object newValue) {
            
        }

        @Override
        public int getIndexOfChild(Object parent, Object child) {
            if(parent.equals(getRoot())){
                return courses.indexOf(child);
            } else if(parent instanceof CourseCategory){
                CourseCategory category = (CourseCategory)parent;
                ArrayList<Course> c = new ArrayList<>(category.getCourses());
                sortCourses(c);
                return c.indexOf(child);
            }
            return 0;
        }

        @Override
        public void addTreeModelListener(TreeModelListener listener) {
            listeners.add(listener);
        }

        @Override
        public void removeTreeModelListener(TreeModelListener listener) {
            listeners.remove(listener);
        }
    }
    
    private interface CourseEventModel{
        public CourseEvent getCourseEventAt(int selectedRow);
    }
    
    private class CourseEventsTableModel extends AbstractTableModel implements CourseEventModel{
        
        private ArrayList<CourseEvent> events;
        private String[] columns = new String[]{
            getString("course_start_date"),
            getString("course_end_date"),
            getString("course_comments")
        };
        
        public CourseEventsTableModel(ArrayList<CourseEvent> events){
            this.events = events;
        }

        @Override
        public String getColumnName(int column) {
            return columns[column];
        }
        
        @Override
        public int getRowCount() {
            return events.size();
        }

        @Override
        public int getColumnCount() {
            return columns.length;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            CourseEvent event = events.get(rowIndex);
            String value = "";
            switch(columnIndex){
                case 0:
                    value = event.getStartDate().toString();
                    break;
                case 1:
                    value = event.getEndDate().toString();
                    break;
                case 2:
                    value = event.getComments();
                    break;
            }
            
            return value;
        }
    
        @Override
        public CourseEvent getCourseEventAt(int selectedRow){
            return events.get(selectedRow);
        }
    
    }
    
    private class CourseCompaniesTableModel extends AbstractTableModel{
        
        private ArrayList<Company> companies;
        private String[] columns = new String[]{
            getString("course_event_student_company"),
            getString("documents")
        };
        
        public CourseCompaniesTableModel(ArrayList<Company> companies){
            this.companies = companies;
        }

        @Override
        public String getColumnName(int column) {
            return columns[column];
        }
        
        @Override
        public int getRowCount() {
            return companies.size();
        }

        @Override
        public int getColumnCount() {
            return columns.length;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            Company company = companies.get(rowIndex);
            String value = "";
            switch(columnIndex){
                case 0:
                    value = company.getName();
                    break;
                case 1:
                    value = getString("documents_create");
                    break;
            }
            return value;
        }

        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            if(columnIndex == 1){
                return true;
            }
            return false;
        }
        
        public Company getCompanyAt(int selectedRow){
            return companies.get(selectedRow);
        }
    }

    private class CourseWorkersTableModel extends AbstractTableModel{
        
        private ArrayList<Worker> workers;
        private String[] columns = new String[]{
            getString("course_event_student_name")
        };
        
        public CourseWorkersTableModel(ArrayList<Worker> workers){
            this.workers = workers;
        }

        @Override
        public String getColumnName(int column) {
            return columns[column];
        }
        
        @Override
        public int getRowCount() {
            return workers.size();
        }

        @Override
        public int getColumnCount() {
            return columns.length;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            Worker worker = workers.get(rowIndex);
            String value = "";
            switch(columnIndex){
                case 0:
                    value = String.format("%s %s", worker.getName(), worker.getSurname());
                    break;
            }
            return value;
        }
    }
    
    private class ExpiredCellRenderer extends DefaultTableCellRenderer{
        
        public ExpiredCellRenderer(){
            super();
            setOpaque(true);
        }
        
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        
            if(table.getModel() instanceof CourseEventModel){
                CourseEventModel model = (CourseEventModel)table.getModel();
                CourseEvent event = model.getCourseEventAt(row);
                Date now = new Date();
                if(event.getEndDate().before(now)){
                    c.setBackground(new Color(238, 238, 238));
                }else{
                    c.setBackground(new Color(255, 255, 255));
                }
            }
            return c;
        }
        
    }
    
    private class WorkerCompanyCoursesTableModel extends AbstractTableModel implements CourseEventModel{
        
        private ArrayList<CourseEvent> courseEvents;
        private String columns[] = new String[]{
            getString("course"),
            getString("course_start_date"),
            getString("course_end_date")
        };
        
        public WorkerCompanyCoursesTableModel(ArrayList<CourseEvent> courseEvents){
            this.courseEvents = courseEvents;
        }
        
        @Override
        public int getRowCount() {
            return courseEvents.size();
        }

        @Override
        public int getColumnCount() {
            return columns.length;
        }
        
        @Override
        public String getColumnName(int column) {
            return columns[column];
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            CourseEvent event = courseEvents.get(rowIndex);
            Course course = event.getCourse();
            String value = "";
            switch(columnIndex){
                case 0:
                    value = course.getName();
                    break;
                case 1:
                    value = event.getStartDate().toString();
                    break;
                case 2:
                    value = event.getEndDate().toString();
                    break;
            }
            return value;
        }   

        @Override
        public CourseEvent getCourseEventAt(int selectedRow) {
            return courseEvents.get(selectedRow);
        }
    }
    
    private class CompaniesTreeModel implements TreeModel{
        
        private ArrayList<Company> companies;
        
        public CompaniesTreeModel(ArrayList<Company> companies){
            this.companies = companies;
        }
        
        @Override
        public Object getRoot() {
            return getString("companies");
        }

        @Override
        public Object getChild(Object parent, int index) {
            if(parent.equals(getRoot())){
                return companies.get(index);
            } else if(parent instanceof Company){
                Company company = (Company)parent;
                ArrayList<Worker> workers = new ArrayList<>(company.getWorkers());
                sortWorkers(workers);
                return workers.get(index);
            }
            return null;
        }

        @Override
        public int getChildCount(Object parent) {
            if(parent.equals(getRoot())){
                return companies.size();
            } else if(parent instanceof Company){
                Company company = (Company)parent;
                if(company.getWorkers() != null && company.getWorkers().size() > 0){
                    return company.getWorkers().size();
                }
            }
            return 0;    
        }

        @Override
        public boolean isLeaf(Object node) {
            if(node instanceof Company){
                Company company = (Company)node;
                if(company.getWorkers() != null && company.getWorkers().size() > 0){
                    return false;
                }
            } else if(node.equals(getRoot())){
                return false;
            }
            return true;
        }

        @Override
        public void valueForPathChanged(TreePath path, Object newValue) {}

        @Override
        public int getIndexOfChild(Object parent, Object child) {
            if(parent.equals(getRoot())){
                return companies.indexOf(child);
            } else if(parent instanceof Company){
                Company company = (Company)parent;
                ArrayList<Worker> workers = new ArrayList<>(company.getWorkers());
                sortWorkers(workers);
                return workers.indexOf(child);
            }
            return 0;
        }

        @Override
        public void addTreeModelListener(TreeModelListener l) {}

        @Override
        public void removeTreeModelListener(TreeModelListener l) {}
        
    }
    
    private class AccomodationTreeModel implements TreeModel{
        
        private ArrayList<Accomodation> accomodations;
        
        public AccomodationTreeModel(ArrayList<Accomodation> accomodations){
            this.accomodations = accomodations;
        }
        
        @Override
        public Object getRoot() {
            return getString("accomodation_place");
        }

        @Override
        public Object getChild(Object parent, int index) {
            if(parent.equals(getRoot())){
                return accomodations.get(index);
            }
            return null;
        }

        @Override
        public int getChildCount(Object parent) {
            if(parent.equals(getRoot())){
                return accomodations.size();
            }
            return 0;    
        }

        @Override
        public boolean isLeaf(Object node) {
            if(node.equals(getRoot())){
                return false;
            }
            return true;
        }

        @Override
        public void valueForPathChanged(TreePath path, Object newValue) {}

        @Override
        public int getIndexOfChild(Object parent, Object child) {
            if(parent.equals(getRoot())){
                return accomodations.indexOf(child);
            }
            return 0;
        }

        @Override
        public void addTreeModelListener(TreeModelListener l) {}

        @Override
        public void removeTreeModelListener(TreeModelListener l) {}  
    }
    
    private static class TreeUtil{

        public static boolean isDescendant(TreePath path1, TreePath path2){
            int count1 = path1.getPathCount();
            int count2 = path2.getPathCount();
            if(count1<=count2)
                return false;
            while(count1!=count2){
                path1 = path1.getParentPath();
                count1--;
            }
            return path1.equals(path2);
        }

        public static String getExpansionState(JTree tree, int row){
            TreePath rowPath = tree.getPathForRow(row);
            StringBuilder buf = new StringBuilder();
            int rowCount = tree.getRowCount();
            for(int i=row; i<rowCount; i++){
                TreePath path = tree.getPathForRow(i);
                if(i==row || isDescendant(path, rowPath)){
                    if(tree.isExpanded(path)){
                        buf.append(",");
                        buf.append(String.valueOf(i-row));
                    }
                }else
                    break;
            }
            return buf.toString();
        }

        public static void restoreExpanstionState(JTree tree, int row, String expansionState){
            StringTokenizer stok = new StringTokenizer(expansionState, ",");
            while(stok.hasMoreTokens()){
                int token = row + Integer.parseInt(stok.nextToken());
                tree.expandRow(token);
            }
        }
    }
}
